<?php

declare(strict_types=1);

namespace App\CustHub\Service;

use App\CustHub\Constants\ContactTaskCenterTyperConstants;
use App\CustHub\Dto\ContactTcContentDto;
use App\CustHub\Mapper\ChContactMapper;
use App\CustHub\Mapper\ChRoomMemberMapper;
use App\CustHub\Mapper\ChSmartPushSchemeTargetTaskMapper;
use App\CustHub\Model\ChRoomMember;
use App\CustHub\Model\ChSmartPushScheme;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;

/**
 * 推送方案目标任务服务类
 */
class ChSmartPushSchemeTargetTaskService extends AbstractService
{
    public $mapper;

    #[Inject]
    protected ChContactMapper $contactMapper;

    #[Inject]
    protected ChRoomMemberMapper $roomMemberMapper;

    public function __construct(ChSmartPushSchemeTargetTaskMapper $mapper)
    {
        $this->mapper = $mapper;
    }


    public function timedHandler(): void
    {
        $list = $this->mapper->model::query()
            ->where('begin_time','<=',time())
            ->where('is_running',0)
            ->where('status',0)
            ->get();

        foreach ($list as $item) {

            $this->mapper->update($item->id,[
                'is_running' => 1
            ]);

            $contactInfo = $this->contactMapper->findByRobotIdAndUserId($item->robot_id, $item->user_id);
            $roomWxids = $this->roomMemberMapper->getRoomWxidsByUserId($item->user_id);
            $userData = [
                "corp_tag" => $contactInfo->corpTags()->pluck('id')->toArray(),  // 用户的企业标签
                "smart_tag" => $contactInfo->smartTags()->pluck('id')->toArray(),  // 用户的智能标签
                "gender" => $contactInfo->gender,  // 用户的性别
                "source" => $contactInfo->source,  // 用户的来源
                "created_at" =>datetime($contactInfo->create_time),  // 用户的创建时间
                "in_room" => $roomWxids,  // 用户所在的群
                "quite_room" => $roomWxids,  // 用户未加入的群
                "make_time" => $contactInfo->add_customer_time,  // 用户的好友时长（2天）
                "last_send_msg_time" => $contactInfo->last_send_msg_time,  // 用户最后发言时间
            ];
            if($this->checkUserConditions($userData,$item->push_tgt_cfg['cfg'])){
                //用户满足条件，执行后续操作
                if(!empty($item->push_tgt_cfg['corp_tag_ids'])){
                    $content = new ContactTcContentDto();
                    $content->setContactIds([$contactInfo->id]);
                    $content->setTagIds(array_unique($item->push_tgt_cfg['corp_tag_ids']));
                    container()->get(ChContactTaskCenterService::class)->addTask($contactInfo->uid,$contactInfo->main_uid,ContactTaskCenterTyperConstants::PUT_ON_CORP_TAG,$content);
                }

                if(!empty($item->push_tgt_cfg['smart_tag_ids'])){
                    //智能标签
                    $content = new ContactTcContentDto();
                    $content->setContactIds([$contactInfo->id]);
                    $content->setTagIds(array_unique($item->push_tgt_cfg['smart_tag_ids']));
                    container()->get(ChContactTaskCenterService::class)->addTask($contactInfo->uid,$contactInfo->main_uid,ContactTaskCenterTyperConstants::PUT_ON_SMART_TAG,$content);
                }

                $this->mapper->update($item->id,[
                    'is_running' => 0,
                    'status' => 1
                ]);
                //更新目标完成数量
                ChSmartPushScheme::query()
                    ->where('id',$item->scheme_id)
                    ->increment('completed_count');
            }else{
                //目标未完成
                $this->mapper->update($item->id,[
                    'is_running' => 0,
                    'status' => 2
                ]);
            }
        }
    }

    // 检查子条件（按条件中的 op 判断是 "and" 还是 "or"）
    function checkSubConditions($userData, $subConditions, $op) {
        $result = ($op === 'and');

        foreach ($subConditions as $condition) {
            $conditionResult = $this->checkCondition($userData, $condition);
            if ($op === 'or') {
                $result = $result || $conditionResult;
                if ($result) break; // 如果是 "or" 逻辑，满足任意一个就可以
            } elseif ($op === 'and') {
                $result = $result && $conditionResult;
                if (!$result) break; // 如果是 "and" 逻辑，满足所有条件才行
            }
        }

        return $result;
    }

// 检查用户是否满足查询条件
    function checkUserConditions($userData, $query): bool
    {
        if ($query['cond'] === 'or') {
            foreach ($query['items'] as $item) {
                $result = $this->checkSubConditions($userData, $item['items'], $item['op']);
                if ($result) {
                    return true; // 只要满足其中一个大条件
                }
            }
            return false; // 如果没有任何条件满足
        } elseif ($query['cond'] === 'and') {
            foreach ($query['items'] as $item) {
                $result = $this->checkSubConditions($userData, $item['items'], $item['op']);
                if (!$result) {
                    return false; // 如果有任何一个子条件不满足就返回 false
                }
            }
            return true; // 所有条件都满足
        }
        return false;
    }

    // 检查条件函数
    private function checkCondition($userData, $condition): bool
    {
        if($condition['event'] == 'make_time'){
            return $this->checkDuration($userData[$condition['event']], $condition);
        }

        switch ($condition['op']) {
            case 'in':
                if(is_array($userData[$condition['event']])){
                    $result = array_intersect($userData[$condition['event']], $condition['value']);
                    return !empty($result);
                }else{
                    return in_array($userData[$condition['event']] ?? null, $condition['value']);
                }
            case 'not in':
                if(is_array($userData[$condition['event']])){
                    $result = array_intersect($userData[$condition['event']], $condition['value']);
                    return empty($result);
                }else{
                    return !in_array($userData[$condition['event']] ?? null, $condition['value']);
                }
            case 'greater':
                return $userData[$condition['event']] > $condition['value']['val'];
            case 'equal':
                return $userData[$condition['event']] == $condition['value']['val'];
            case 'less':
                return $userData[$condition['event']] < $condition['value']['val'];
            case 'later':
                $userDate = strtotime($userData[$condition['event']] ?? '');
                $startDate = strtotime($condition['value']['start_time']);
                return $userDate > $startDate;
            case 'earlier':
                $userDate = strtotime($userData[$condition['event']] ?? '');
                $startDate = strtotime($condition['value']['start_time']);
                return $userDate < $startDate;
            case 'range_within':
                $userDate = strtotime($userData[$condition['event']] ?? '');
                $startDate = strtotime($condition['value']['start_time']);
                $endDate = strtotime($condition['value']['end_time']);
                return $userDate >= $startDate && $userDate <= $endDate;
            case 'out_of_range':
                $userDate = strtotime($userData[$condition['event']] ?? '');
                $startDate = strtotime($condition['value']['start_time']);
                $endDate = strtotime($condition['value']['end_time']);
                return $userDate < $startDate || $userDate > $endDate;
            case 'in_room':
                return in_array($userData[$condition['event']] ?? [], $condition['value']);
            case 'quite_room':
                return !in_array($userData[$condition['event']] ?? [], $condition['value']);
            default:
                return false;
        }
    }

    // 检查好友时长
    private function checkDuration($makeTime, $condition): bool
    {
        $currentTime = time();
        $makeTime = strtotime($makeTime);
        $duration = ($currentTime - $makeTime);

        switch ($condition['value']['unit']) {
            case 'days':
                $duration /= (60 * 60 * 24);
                break;
            case 'hours':
                $duration /= (60 * 60);
                break;
            case 'minutes':
                $duration /= 60;
                break;
        }

        switch ($condition['op']) {
            case 'greater':
                return $duration > $condition['value']['val'];
            case 'greater_equal':
                return $duration >= $condition['value']['val'];
            case 'equal':
                return $duration == $condition['value']['val'];
            case 'less':
                return $duration < $condition['value']['val'];
            case 'less_equal':
                return $duration <= $condition['value']['val'];
            default:
                return false;
        }
    }
}